/*=============================================================================
DeviceManager.cpp : Device manager
Copyright (c) 2001-2009 Crytek Studios. All Rights Reserved.

Revision history:
* Created by Khonich Andrey

=============================================================================*/

#include "StdAfx.h"
#include "../DriverD3D.h"

CDeviceManager::CDeviceManager(D3DDevice *pDevice)
{
  m_pDevice = pDevice;
}

CDeviceTexture::CDeviceTexture (const CDeviceTexture& b)
{
	//[Alexey] This shouldn't happens
	//__debugbreak();
}

void CDeviceTexture::free()
{









}





























#ifdef DEVMAN_USE_STAGING_POOL
D3DTexture* CDeviceManager::AllocateStagingTexture(D3DTexture* pForTex)
{
	D3D11_TEXTURE2D_DESC Desc;
	memset(&Desc, 0, sizeof(Desc));

	pForTex->GetDesc(&Desc);
	Desc.Usage = D3D11_USAGE_STAGING;
	Desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
	Desc.BindFlags = 0;

	D3DTexture* pStagingTexture = NULL;

	StagingPoolVec::iterator it = std::find(m_stagingPool.begin(), m_stagingPool.end(), Desc);
	if (it == m_stagingPool.end())
	{
		gcpRendD3D->m_pd3dDevice->CreateTexture2D(&Desc, NULL, &pStagingTexture);

#ifndef _RELEASE
		if (pStagingTexture)
		{
			D3D11_TEXTURE2D_DESC stagingDesc;
			memset(&stagingDesc, 0, sizeof(stagingDesc));

			pStagingTexture->GetDesc(&stagingDesc);
			stagingDesc.Usage = D3D11_USAGE_STAGING;
			stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
			stagingDesc.BindFlags = 0;

			if (memcmp(&stagingDesc, &Desc, sizeof(Desc)) != 0)
				__debugbreak();
		}
#endif
	}
	else
	{
		pStagingTexture = it->pStagingTexture;
		m_stagingPool.erase(it);
	}

	return pStagingTexture;
}

void CDeviceManager::ReleaseStagingTexture(ID3D11Texture2D* pStagingTex)
{
	D3D11_TEXTURE2D_DESC Desc;
	memset(&Desc, 0, sizeof(Desc));

	pStagingTex->GetDesc(&Desc);
	Desc.Usage = D3D11_USAGE_STAGING;
	Desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
	Desc.BindFlags = 0;

	StagingTextureDef def;
	def.desc = Desc;
	def.pStagingTexture = pStagingTex;
	m_stagingPool.push_back(def);
}
#endif

D3DBaseTexture* CDeviceTexture::GetBaseTexture()
{



	return m_pD3DTexture;
}

HRESULT CDeviceManager::Create2DTexture(uint32 nWidth, uint32 nHeight, uint32 nMips, uint32 nUsage, D3DFormat Format, D3DPOOL Pool, LPDEVICETEXTURE* ppDevTexture, STextureInfo* pTI, bool bShouldBeCreated, int8 nPriority)
{
  HRESULT hr = S_OK;

  CDeviceTexture *pDeviceTexture = 0;//*/ new CDeviceTexture();
  D3DTexture *pD3DTex = NULL;





















































#if defined (DIRECT3D9)
  hr = m_pDevice->CreateTexture(nWidth, nHeight, nMips, nUsage & ~USAGE_CUSTOM, Format, Pool, &pD3DTex, NULL);
#elif defined (DIRECT3D10) || defined (PS3) 	

  uint32 nBindFlags = (nUsage & USAGE_READBACK)? 0 : D3D11_BIND_SHADER_RESOURCE; 
  if (nUsage & USAGE_DEPTH_STENCIL)
    nBindFlags |= D3D11_BIND_DEPTH_STENCIL;
  else
  if (nUsage & USAGE_RENDER_TARGET)
    nBindFlags |= D3D11_BIND_RENDER_TARGET;

	uint32 nMiscFlags = 0;
	if( nUsage & USAGE_AUTOGENMIPS)
		nMiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;





  D3D11_TEXTURE2D_DESC Desc;
  ZeroStruct(Desc);  Desc.Width = nWidth;
  Desc.Height = nHeight;
  Desc.MipLevels = nMips;
  Desc.Format = Format;
  Desc.ArraySize = pTI ? pTI->m_nArraySize : 1;
  Desc.BindFlags = nBindFlags;
  Desc.CPUAccessFlags = (nUsage & USAGE_DYNAMIC) ? D3D11_CPU_ACCESS_WRITE : 0;
	Desc.CPUAccessFlags |= (nUsage & USAGE_READBACK) ? D3D11_CPU_ACCESS_READ : 0;

  Desc.Usage = (nUsage & USAGE_DYNAMIC ) ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
	Desc.Usage = (nUsage & USAGE_READBACK) ? D3D11_USAGE_STAGING: Desc.Usage;
	
  Desc.SampleDesc.Count = pTI ? pTI->m_nMSAASamples : 1;
  Desc.SampleDesc.Quality = pTI ? pTI->m_nMSAAQuality : 0;
	// AntonK: supported only by DX11 feature set
	// needs to be enabled for pure DX11 context
	//if(nUsage & USAGE_STREAMING)
	//	Desc.MiscFlags = D3D11_RESOURCE_MISC_RESOURCE_CLAMP;
  //if (nUsage & USAGE_STREAMING)
  //	Desc.CPUAccessFlags |= D3D11_CPU_ACCESS_READ;
	Desc.MiscFlags = nMiscFlags;

  D3D11_SUBRESOURCE_DATA *pSRD = NULL;
  D3D11_SUBRESOURCE_DATA SRD[20];
  if (pTI && pTI->m_pData)
  {
    pSRD = &SRD[0];
    for (int i=0; i<nMips; i++)
    {
      SRD[i].pSysMem = pTI->m_pData[i].pSysMem;
      SRD[i].SysMemPitch = pTI->m_pData[i].SysMemPitch;
      SRD[i].SysMemSlicePitch = pTI->m_pData[i].SysMemSlicePitch;
    }
  }
  hr = m_pDevice->CreateTexture2D(&Desc, pSRD, &pD3DTex);
#endif

	if(SUCCEEDED(hr) && pDeviceTexture == 0)
		pDeviceTexture = new CDeviceTexture();
	
	if(SUCCEEDED(hr) && pD3DTex)
		pDeviceTexture->m_pD3DTexture = pD3DTex;
	else
		SAFE_DELETE(pDeviceTexture);

  *ppDevTexture = pDeviceTexture;

  return hr;
}

HRESULT CDeviceManager::CreateCubeTexture(uint32 nSize, uint32 nMips, uint32 nUsage, D3DFormat Format, D3DPOOL Pool, LPDEVICETEXTURE* ppDevTexture, STextureInfo* pTI, bool bShouldBeCreated)
{
  HRESULT hr = S_OK;

  CDeviceTexture *pDeviceTexture = 0;//new CDeviceTexture();
  D3DCubeTexture *pD3DTex = NULL;



















#if defined (DIRECT3D9)
  hr = m_pDevice->CreateCubeTexture(nSize, nMips, nUsage & ~USAGE_CUSTOM, Format, Pool, &pD3DTex, NULL);
#elif defined (DIRECT3D10) || defined (PS3) 
  uint32 nBindFlags = D3D11_BIND_SHADER_RESOURCE;
  if (nUsage & USAGE_DEPTH_STENCIL)
    nBindFlags |= D3D11_BIND_DEPTH_STENCIL;
  else
  if (nUsage & USAGE_RENDER_TARGET)
    nBindFlags |= D3D11_BIND_RENDER_TARGET;
  D3D11_TEXTURE2D_DESC Desc;
  ZeroStruct(Desc);
  Desc.Width = nSize;
  Desc.Height = nSize;
  Desc.MipLevels = nMips;
  Desc.Format = Format;
  Desc.ArraySize = 6;
  Desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
  Desc.CPUAccessFlags = (nUsage & USAGE_DYNAMIC) ? D3D11_CPU_ACCESS_WRITE : 0;
  Desc.Usage = (nUsage & USAGE_DYNAMIC) ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
  Desc.SampleDesc.Count = 1;
  Desc.SampleDesc.Quality = 0;
  Desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
	// AntonK: supported only by DX11 feature set
	// needs to be enabled for pure DX11 context
	//if(nUsage & USAGE_STREAMING)
	//	Desc.MiscFlags |= D3D11_RESOURCE_MISC_RESOURCE_CLAMP;
	D3D11_SUBRESOURCE_DATA *pSRD = NULL;
  D3D11_SUBRESOURCE_DATA SRD[g_nD3D10MaxSupportedSubres];
  if (pTI && pTI->m_pData)
  {
    pSRD = &SRD[0];
    for (int j=0; j<6; j++)
    {
      for (int i=0; i<nMips; i++)
      {
        int nSubresInd = j * nMips + i;
        SRD[nSubresInd].pSysMem = pTI->m_pData[nSubresInd].pSysMem;
        SRD[nSubresInd].SysMemPitch = pTI->m_pData[nSubresInd].SysMemPitch;
        SRD[nSubresInd].SysMemSlicePitch = pTI->m_pData[nSubresInd].SysMemSlicePitch;
      }
    }
  }
  hr = m_pDevice->CreateTexture2D(&Desc, pSRD, &pD3DTex);
#endif

	if(SUCCEEDED(hr) && pDeviceTexture == 0)
		pDeviceTexture = new CDeviceTexture();

	if(SUCCEEDED(hr) && pD3DTex)
		pDeviceTexture->m_pD3DTexture = pD3DTex;
	else
		SAFE_DELETE(pDeviceTexture);

  *ppDevTexture = pDeviceTexture;

  return hr;
}

HRESULT CDeviceManager::CreateVolumeTexture(uint32 nWidth, uint32 nHeight, uint32 nDepth, uint32 nMips, uint32 nUsage, D3DFormat Format, D3DPOOL Pool, LPDEVICETEXTURE* ppDevTexture, STextureInfo* pTI)
{
  HRESULT hr = S_OK;

  CDeviceTexture *pDeviceTexture = new CDeviceTexture();
  D3DVolumeTexture *pD3DTex = NULL;
#if defined (DIRECT3D9) || defined (XENON)
  hr = m_pDevice->CreateVolumeTexture(nWidth, nHeight, nDepth, nMips, nUsage & ~USAGE_CUSTOM, Format, Pool, &pD3DTex, NULL);
#elif defined (DIRECT3D10) || defined (PS3) 
  uint32 nBindFlags = D3D11_BIND_SHADER_RESOURCE;
  if (nUsage & USAGE_DEPTH_STENCIL)
    nBindFlags |= D3D11_BIND_DEPTH_STENCIL;
  else
  if (nUsage & USAGE_RENDER_TARGET)
    nBindFlags |= D3D11_BIND_RENDER_TARGET;
  D3D11_TEXTURE3D_DESC Desc;
  ZeroStruct(Desc);
  Desc.Width = nWidth;
  Desc.Height = nHeight;
  Desc.Depth = nDepth;
  Desc.MipLevels = nMips;
  Desc.Format = Format;
  Desc.BindFlags = nBindFlags;
  Desc.CPUAccessFlags = 0;
  Desc.Usage = (D3D11_USAGE)nUsage;
  Desc.MiscFlags = 0;
  D3D11_SUBRESOURCE_DATA *pSRD = NULL;
  D3D11_SUBRESOURCE_DATA SRD[20];
  if (pTI && pTI->m_pData)
  {
    pSRD = &SRD[0];
    for (int i=0; i<nMips; i++)
    {
      SRD[i].pSysMem = pTI->m_pData[i].pSysMem;
      SRD[i].SysMemPitch = pTI->m_pData[i].SysMemPitch;
      SRD[i].SysMemSlicePitch = pTI->m_pData[i].SysMemSlicePitch;
    }
  }
  hr = m_pDevice->CreateTexture3D(&Desc, pSRD, &pD3DTex);
#endif

	if(SUCCEEDED(hr) && pD3DTex)
		pDeviceTexture->m_pD3DTexture = pD3DTex;
	else
		SAFE_DELETE(pDeviceTexture);

  *ppDevTexture = pDeviceTexture;

  return hr;
}

HRESULT CDeviceManager::CreateBuffer(
	uint32 nSize
	, uint32 elemSize
	, int32 nUsage
	, int32 nBindFlags
	, D3DBuffer **ppBuff)
{
	MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "CreateBuffer");
  HRESULT hr = S_OK;

# ifndef _RELEASE
	// ToDo verify that the usage and bindflags are correctly set (e.g certain
	// bit groups are mutually exclusive).
# endif 

#if defined (DIRECT3D9) || defined(XENON)
	signed dynamicMask = (iszero(nUsage & (USAGE_DEFAULT|USAGE_DYNAMIC|USAGE_STAGING|USAGE_CPU_READ))-1);
	D3DPOOL Pool = (D3DPOOL)(D3DPOOL_DEFAULT & dynamicMask | D3DPOOL_MANAGED & ~dynamicMask); 
	uint32 nD3DUsage = 0u;
	nD3DUsage |= (D3DUSAGE_DYNAMIC & dynamicMask);
	nD3DUsage |= (D3DUSAGE_WRITEONLY & -iszero(nUsage & USAGE_CPU_READ));



 	switch(nBindFlags)
	{
		case BIND_VERTEX_BUFFER:
			hr = m_pDevice->CreateVertexBuffer(nSize*elemSize, nD3DUsage, 0, Pool, (D3DVertexBuffer**)ppBuff, NULL);
			break;
		case BIND_INDEX_BUFFER:
			hr = m_pDevice->CreateIndexBuffer(
				nSize*elemSize, 
				nD3DUsage, 
				((elemSize==sizeof(uint16)||elemSize==sizeof(uint8)) ? D3DFMT_INDEX16 : D3DFMT_INDEX32), 
				Pool, 
				(D3DIndexBuffer**)ppBuff, 
				NULL);
			break;

		case BIND_CONSTANT_BUFFER:
		case BIND_SHADER_RESOURCE:
		case BIND_STREAM_OUTPUT:
		case BIND_RENDER_TARGET:
		case BIND_DEPTH_STENCIL:
		default:
			CryFatalError("trying to create unsupported buffer type");
			break;
	}
#elif defined (DIRECT3D10) || defined (PS3) 

  D3D11_BUFFER_DESC BufDesc;
  ZeroStruct(BufDesc);

  BufDesc.ByteWidth = nSize*elemSize;
	int nD3DUsage = D3D11_USAGE_DEFAULT;
  nD3DUsage |= (D3D11_USAGE_DYNAMIC & (iszero(nUsage & USAGE_DYNAMIC)-1));
	nD3DUsage |= (D3D11_USAGE_IMMUTABLE & (iszero(nUsage & USAGE_IMMUTABLE)-1));
	nD3DUsage |= (D3D11_USAGE_STAGING & (iszero(nUsage & USAGE_STAGING)-1));
	BufDesc.Usage = (D3D11_USAGE)nD3DUsage; 

# if !defined(PS3)
	if (BufDesc.Usage  != D3D11_USAGE_STAGING)
# endif
	{
 		switch(nBindFlags)
		{
			case BIND_VERTEX_BUFFER:
				BufDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
				break;
			case BIND_INDEX_BUFFER:
				BufDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
				break;

			case BIND_CONSTANT_BUFFER:
			case BIND_SHADER_RESOURCE:
			case BIND_STREAM_OUTPUT:
			case BIND_RENDER_TARGET:
			case BIND_DEPTH_STENCIL:
				CryFatalError("trying to create (currently) unsupported buffer type");
				break; 

			default:
				CryFatalError("trying to create unknown buffer type");
				break;
		}	
	}
# if !defined(PS3)
	else 
		BufDesc.BindFlags = 0; 
# endif

	BufDesc.CPUAccessFlags = 0; 

	if (BufDesc.Usage != D3D11_USAGE_DEFAULT && BufDesc.Usage != D3D11_USAGE_IMMUTABLE)
	{
		BufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE & (iszero(nUsage & USAGE_CPU_WRITE)-1);
		BufDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_READ & (iszero(nUsage & USAGE_CPU_READ)-1);
	}

  BufDesc.MiscFlags = 0; 

  if (m_pDevice)
    hr = m_pDevice->CreateBuffer(&BufDesc, NULL, ppBuff);
	CHECK_HRESULT(hr);
#endif

	return hr; 
}



size_t CDeviceTexture::GetDeviceSize() const
{
	size_t counted = m_nBaseAllocatedSize;




	return counted;
}











//=============================================================================

int32 CDeviceTexture::Release()
{
  int32 nRef = -1;
  if (m_pD3DTexture)
  {
#if !defined(PS3) && !defined(CAFE)





















			nRef = m_pD3DTexture->Release();



#endif
    m_pD3DTexture = NULL;
  }

#ifdef DEVMAN_USE_STAGING_POOL
	if (m_pStagingTexture)
	{
		gcpRendD3D->m_DevMan.ReleaseStagingTexture(m_pStagingTexture);
		m_pStagingTexture = NULL;
	}
#endif

  bool bNoDelete=false; 
#if defined(DIRECT3D10)
  bNoDelete=m_bNoDelete; 
#endif 

  if (nRef <= 0 && !bNoDelete)
    delete this;

  return nRef;
}

HRESULT CDeviceTexture::UnlockRect(uint32 nLevel)
{
  if (!m_pD3DTexture)
    return E_FAIL;
  D3DTexture *pD3DTexture = Get2DTexture();
#if defined(DIRECT3D9) || defined(XENON)
  return pD3DTexture->UnlockRect(nLevel);


#elif defined(DIRECT3D10)
  if (m_pStagingTexture)
  {
    gcpRendD3D->m_pd3dDeviceContext->Unmap(m_pStagingTexture, nLevel);
#ifdef DEVMAN_USE_STAGING_POOL
		if (m_bStagingTextureAllocedOnLock)
		{
			gcpRendD3D->m_DevMan.ReleaseStagingTexture(m_pStagingTexture);
			m_pStagingTexture = NULL;
			m_bStagingTextureAllocedOnLock = false;
		}
#endif
    //SAFE_RELEASE(m_pStagingTexture);
  }
  else
    gcpRendD3D->m_pd3dDeviceContext->Unmap(pD3DTexture, nLevel);
#endif
  return S_OK;
}

HRESULT CDeviceTexture::UnlockRect(int32 nCubeSide, uint32 nLevel)
{
  if (!m_pD3DTexture)
    return E_FAIL;
	if(nCubeSide >= 0)
	{
		D3DCubeTexture *pD3DTexture = GetCubeTexture();
	#if defined (DIRECT3D9) || defined (XENON)
		return pD3DTexture->UnlockRect((D3DCUBEMAP_FACES)nCubeSide, nLevel);
	#elif defined (DIRECT3D10) || defined (PS3) 
		gcpRendD3D->m_pd3dDeviceContext->Unmap(pD3DTexture, D3D11CalcSubresource(nLevel, nCubeSide, 1));
	#endif
		return S_OK;
	}
	else
	{
		return UnlockRect(nLevel);
	}
}

HRESULT CDeviceTexture::UnlockBox(uint32 nLevel)
{
  if (!m_pD3DTexture)
    return E_FAIL;
  D3DVolumeTexture *pD3DTexture = GetVolumeTexture();
#if defined(DIRECT3D9) || defined(XENON)
  return pD3DTexture->UnlockBox(nLevel);


#elif defined(DIRECT3D10)
  gcpRendD3D->m_pd3dDeviceContext->Unmap(pD3DTexture, D3D11CalcSubresource(nLevel, 0, 1));
#endif
  return S_OK;
}

#if defined(DIRECT3D10) && !defined(PS3)
void CDeviceTexture::CopyToStagingTexture(uint32 nLevel, bool bFromLock)
{
	D3DTexture *pD3DTexture = Get2DTexture();

#ifdef DEVMAN_USE_STAGING_POOL
	if (!m_pStagingTexture)
	{
		m_pStagingTexture = gcpRendD3D->m_DevMan.AllocateStagingTexture(pD3DTexture);
		m_bStagingTextureAllocedOnLock = bFromLock;
	}
#else
	D3D11_TEXTURE2D_DESC Desc;
	pD3DTexture->GetDesc(&Desc);
	if (!m_pStagingTexture)
	{
		Desc.Usage = D3D11_USAGE_STAGING;
		Desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
		Desc.BindFlags = 0;
		gcpRendD3D->m_pd3dDevice->CreateTexture2D(&Desc, NULL, &m_pStagingTexture);
	}
#endif
	if (m_pStagingTexture)
	{
		uint32 nSubRes = D3D11CalcSubresource(nLevel, 0, 1);
		gcpRendD3D->m_pd3dDeviceContext->CopySubresourceRegion(m_pStagingTexture, nSubRes, 0, 0, 0, pD3DTexture, nSubRes, NULL);
	}
}
#endif

HRESULT CDeviceTexture::LockRect(uint32 nLevel, STexLock& Data, uint32 nFlags)
{
	assert(nFlags == 0 || IsPowerOfTwo(nFlags));
  if (!m_pD3DTexture 



		)
    return E_FAIL;
  D3DTexture *pD3DTexture = Get2DTexture();
#if defined (DIRECT3D9) || defined (XENON)
  D3DLOCKED_RECT lrct;
  uint32 nLockFlags = 0;
  if (nFlags & LF_DISCARD)
    nLockFlags |= D3DLOCK_DISCARD;
	if (nFlags & LF_READ)
	{
		nLockFlags |= D3DLOCK_READONLY;



	}
  HRESULT hr = pD3DTexture->LockRect(nLevel, &lrct, NULL, nLockFlags);
  Data.pData = (uint8 *)lrct.pBits;
  Data.Pitch = lrct.Pitch;
#elif defined (DIRECT3D10) || defined (PS3) 
#if !defined(PS3)
	if (nFlags & LF_STREAMING)
		CopyToStagingTexture(nLevel, true);
	if (m_pStagingTexture)
		pD3DTexture = m_pStagingTexture;
#endif
	D3D11_MAPPED_SUBRESOURCE lrct;
  uint32 nLockFlags = 0;
  if ((nFlags & LF_READ) || !nFlags) //0 is not a valid Map flag
    nLockFlags |= D3D11_MAP_READ;
  if (nFlags & LF_WRITE)
    nLockFlags |= D3D11_MAP_WRITE;
  if (nFlags & LF_DISCARD)
    nLockFlags |= D3D11_MAP_WRITE_DISCARD;
  HRESULT hr = gcpRendD3D->m_pd3dDeviceContext->Map(pD3DTexture, D3D11CalcSubresource(nLevel, 0, 1), (D3D11_MAP)nLockFlags, 0, &lrct);
  Data.pData = (uint8*)lrct.pData;
  Data.Pitch = lrct.RowPitch;
#endif
  return hr;
}

HRESULT CDeviceTexture::LockRect(int32 nCubeSide, uint32 nLevel, STexLock& Data, uint32 nFlags)
{
	assert(nFlags == 0 || IsPowerOfTwo(nFlags));
	if (!m_pD3DTexture)
    return E_FAIL;

	if(nCubeSide < 0)
		return LockRect(nLevel, Data, nFlags);

  D3DCubeTexture *pD3DTexture = GetCubeTexture();
#if defined (DIRECT3D9) || defined (XENON)
  D3DLOCKED_RECT lrct;
  uint32 nLockFlags = 0;
  if (nFlags & LF_DISCARD)
    nLockFlags |= D3DLOCK_DISCARD;
	if (nFlags & LF_READ)
	{
		nLockFlags |= D3DLOCK_READONLY;



	}
  HRESULT hr = pD3DTexture->LockRect((D3DCUBEMAP_FACES)nCubeSide, nLevel, &lrct, NULL, nLockFlags);
  Data.pData = (uint8 *)lrct.pBits;
  Data.Pitch = lrct.Pitch;
#elif defined (DIRECT3D10) || defined (PS3) 
  D3D11_MAPPED_SUBRESOURCE lrct;
  uint32 nLockFlags = 0;
  if (nFlags & LF_READ)
    nLockFlags |= D3D11_MAP_READ;
  if (nFlags & LF_WRITE)
    nLockFlags |= D3D11_MAP_WRITE;
  if (nFlags & LF_DISCARD)
    nLockFlags |= D3D11_MAP_WRITE_DISCARD;
	D3D11_TEXTURE2D_DESC Desc;
	((ID3D11Texture2D*)m_pD3DTexture)->GetDesc(&Desc);
	HRESULT hr = gcpRendD3D->m_pd3dDeviceContext->Map(pD3DTexture, D3D11CalcSubresource(nLevel, nCubeSide, Desc.MipLevels), (D3D11_MAP)nLockFlags, 0, &lrct);
  Data.pData = (uint8*)lrct.pData;
  Data.Pitch = lrct.RowPitch;
#endif
  return hr;
}

HRESULT CDeviceTexture::LockBox(uint32 nLevel, STexLockBox& Data, uint32 nFlags)
{
	assert(nFlags == 0 || IsPowerOfTwo(nFlags));
	if (!m_pD3DTexture)
    return E_FAIL;
  D3DVolumeTexture *pD3DTexture = GetVolumeTexture();
#if defined (DIRECT3D9) || defined (XENON)
  D3DLOCKED_BOX lrct;
  uint32 nLockFlags = 0;
  if (nFlags & LF_DISCARD)
    nLockFlags |= D3DLOCK_DISCARD;
	if (nFlags & LF_READ)
	{
		nLockFlags |= D3DLOCK_READONLY;



	}
  HRESULT hr = pD3DTexture->LockBox(nLevel, &lrct, NULL, nLockFlags);
  Data.pData = (uint8 *)lrct.pBits;
  Data.RowPitch = lrct.RowPitch;
  Data.SlicePitch = lrct.SlicePitch;
  return hr;


#elif defined (DIRECT3D10) 
  D3D11_MAPPED_SUBRESOURCE lrct;
  uint32 nLockFlags = 0;
  if (nFlags & LF_READ)
    nLockFlags |= D3D11_MAP_READ;
  if (nFlags & LF_WRITE)
    nLockFlags |= D3D11_MAP_WRITE;
  if (nFlags & LF_DISCARD)
    nLockFlags |= D3D11_MAP_WRITE_DISCARD;
  gcpRendD3D->m_pd3dDeviceContext->Map(pD3DTexture, D3D11CalcSubresource(nLevel, 0, 1), (D3D11_MAP)nLockFlags, 0, &lrct);
  Data.pData = (uint8*)lrct.pData;
  Data.RowPitch = lrct.RowPitch;
  Data.SlicePitch = lrct.DepthPitch;
#endif
  return S_OK;
}

CDeviceTexture::~CDeviceTexture()
{






























}

alloc_info_struct *CRenderer::GetFreeChunk(int bytes_count, int nBufSize, PodArray<alloc_info_struct>& alloc_info, const char *szSource)
{
  int best_i = -1;
  int min_size = 10000000;

  // find best chunk
  for(int i=0; i<alloc_info.Count(); i++)
  {
    if(!alloc_info[i].busy)
    {
      if(alloc_info[i].bytes_num >= bytes_count)
      {
        if(alloc_info[i].bytes_num < min_size)
        {
          best_i = i;
          min_size = alloc_info[i].bytes_num;
        }
      }
    }
  }

  if(best_i>=0)
  { // use best free chunk
    alloc_info[best_i].busy = true;
    alloc_info[best_i].szSource = szSource;

    int bytes_free = alloc_info[best_i].bytes_num - bytes_count;
    if(bytes_free>0)
    { 
      // modify reused shunk
      alloc_info[best_i].bytes_num = bytes_count;

      // insert another free shunk
      alloc_info_struct new_chunk;
      new_chunk.bytes_num = bytes_free;
      new_chunk.ptr = alloc_info[best_i].ptr + alloc_info[best_i].bytes_num;
      new_chunk.busy = false;

      if(best_i < alloc_info.Count()-1) // if not last
        alloc_info.InsertBefore(new_chunk, best_i+1);
      else
        alloc_info.Add(new_chunk);
    }

    return &alloc_info[best_i];
  }

  int res_ptr = 0;

  int piplevel = alloc_info.Count() ? (alloc_info.Last().ptr - alloc_info[0].ptr) + alloc_info.Last().bytes_num : 0;
  if(piplevel + bytes_count >= nBufSize)
    return NULL;
  else
    res_ptr = piplevel;

  // register new chunk
  alloc_info_struct ai;
  ai.ptr = res_ptr;
  ai.szSource = szSource;
  ai.bytes_num  = bytes_count;
  ai.busy = true;
  alloc_info.Add(ai);

  return &alloc_info[alloc_info.Count()-1];
}

bool CRenderer::ReleaseChunk(int p, PodArray<alloc_info_struct>& alloc_info)
{
  for(int i=0; i<alloc_info.Count(); i++)
  {
    if(alloc_info[i].ptr == p)
    {
      alloc_info[i].busy = false;

      // delete info about last unused chunks
      while(alloc_info.Count() && alloc_info.Last().busy == false)
        alloc_info.Delete(alloc_info.Count()-1);

      // merge unused chunks
      for(int s=0; s<alloc_info.Count()-1; s++)
      {
        assert(alloc_info[s].ptr < alloc_info[s+1].ptr);

        if(alloc_info[s].busy == false)
        {
          if(alloc_info[s+1].busy == false)
          {
            alloc_info[s].bytes_num += alloc_info[s+1].bytes_num;
            alloc_info.Delete(s+1);
            s--;
          }
        }
      }

      return true;
    }
  }

  return false;
}

